package com.mayikt.member.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSONObject;
import com.mayikt.base.BaseApiService;
import com.mayikt.base.BaseResponse;
import com.mayikt.constants.Constants;
import com.mayikt.core.util.GenerateTokenUtils;
import com.mayikt.core.util.RedisDataSoureceTransaction;
import com.mayikt.member.input.dto.UserLoginInpDTO;
import com.mayikt.member.mapper.UserMapper;
import com.mayikt.member.mapper.UserTokenMapper;
import com.mayikt.member.mapper.entity.UserEntity;
import com.mayikt.member.mapper.entity.UserToken;
import com.mayikt.member.service.MemberLoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Service
public class MemberLoginServiceImpl extends BaseApiService<JSONObject> implements MemberLoginService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserTokenMapper userTokenMapper;
    @Autowired
    private GenerateTokenUtils generateTokenUtils;
    @Autowired
    private RedisDataSoureceTransaction redisDataSoureceTransaction;
    @Autowired
    private MemberServiceImpl memberServiceImpl;
    @Override
    public BaseResponse<com.alibaba.fastjson.JSONObject> login(@RequestBody UserLoginInpDTO userLoginInpDTO) {
//        1.参数校验
        if (StrUtil.isEmpty(userLoginInpDTO.getMobile())){
            return setResultError("手机号不能为空！");
        }
        if (StrUtil.isEmpty(userLoginInpDTO.getPassword())){
            return setResultError("密码不能为空！");
        }
//        2.密码加密
        String password = SecureUtil.md5(userLoginInpDTO.getPassword());
//        3.使用手机号+密码登陆
        UserEntity userEntity = memberServiceImpl.selectUserByMobileAndPassword(userLoginInpDTO.getMobile(),password);
        if (null == userEntity){
            return setResultError("用户名或密码错误！");
        }
        TransactionStatus transactionStatus = null;
        try {
            //登陆成功，判断用户之前登陆过没有
            Long userId = userEntity.getId();
            UserToken userToken = userTokenMapper.selectByUserIdAndLoginTypeAndAvailable(userId, userLoginInpDTO.getLoginType().getLoginTypeStr(),0);
//        手动开启事务
            transactionStatus = redisDataSoureceTransaction.begin();
            if (null != userToken){
                //如果之前登陆过，清除redis 中的token，并将数据库中的token状态改为不可用，然后生成新的token存进redis中
//            1.清除redis  token
                generateTokenUtils.removeToken(userToken.getToken());
                userTokenMapper.updateAvailableByToken(userToken.getToken(),1);
            }
//            2.生成新token
            String tokenPrefix = Constants.MEMBER_TOKEN_KEYPREFIX+userLoginInpDTO.getLoginType().getLoginTypeStr();
//            3.将新token存入redis
            String token = generateTokenUtils.createToken(tokenPrefix, "" + userEntity.getId());
//            4.将新token存入数据库中
            //往数据库插入最新token
            int row = insertToken(token, userEntity.getId(), userLoginInpDTO.getLoginType().getLoginTypeStr(), userLoginInpDTO.getDeviceInfo());
            if (row <= 0){
                redisDataSoureceTransaction.rollback(transactionStatus);
            }
            JSONObject data = new JSONObject();
            data.put("token",token);
            redisDataSoureceTransaction.commit(transactionStatus);
            return setResultSuccess(data);
        } catch (Exception e){
            try {
                redisDataSoureceTransaction.rollback(transactionStatus);
            } catch (Exception e1) {
                e1.printStackTrace();
            }
            return setResultError("系统错误");
        }
    }

    public int insertToken(String token, Long userId, String loginType, String deviceInfo){
        UserToken userToken = new UserToken();
        userToken.setToken(token);
        userToken.setUserId(userId);
        userToken.setLoginType(loginType);
        userToken.setAvailable(0);
        userToken.setDeviceInfo(deviceInfo);
        int rows = userTokenMapper.insert(userToken);
        return rows;
    }
}
